home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 November
/
Macworld (1999-11).dmg
/
Updaters
/
WhiteCap 3.0.4
/
WhiteCap Source.sit
/
WhiteCap Source
/
Common
/
General Tools
/
UtilStr.cpp
< prev
next >
Wrap
Text File
|
1999-07-13
|
18KB
|
1,180 lines
#include "UtilStr.h"
#include "CEgIStream.h"
#include "CEgOStream.h"
#ifdef EG_WIN
#ifndef HBITMAP
#include <windows.h>
#endif
#else
#include <OSUtils.h>
#endif
UtilStr::UtilStr() {
init();
}
UtilStr::UtilStr( const char* inCStr ) {
init();
Append( inCStr );
}
UtilStr::UtilStr( const unsigned char* inStrPtr ) {
init();
Append( inStrPtr );
}
UtilStr::UtilStr( const UtilStr& inStr ) {
init();
Append( &inStr );
}
UtilStr::UtilStr( const UtilStr* inStr ) {
init();
Append( inStr );
}
UtilStr::UtilStr( long inNum ) {
init();
Append( inNum );
}
UtilStr::UtilStr( const void* inPtr, long bytes ) {
init();
Append( inPtr, bytes );
}
UtilStr::~UtilStr() {
if ( mBuf )
delete mBuf;
}
void UtilStr::init() {
mStrLen = 0;
mBufSize = 0;
mBuf = NULL;
}
void UtilStr::Swap( UtilStr& ioStr ) {
long len = mStrLen, size = mBufSize;
char* buf = mBuf;
mBuf = ioStr.mBuf;
mStrLen = ioStr.mStrLen;
mBufSize = ioStr.mBufSize;
ioStr.mBuf = buf;
ioStr.mStrLen = len;
ioStr.mBufSize = size;
}
unsigned char* UtilStr::getPasStr() const {
if ( ! mBuf )
return (unsigned char*) "\0";
if ( mStrLen < 255 )
mBuf[0] = mStrLen;
else
mBuf[0] = 255;
return (unsigned char*) &mBuf[0];
}
char* UtilStr::getCStr() const {
if ( mBuf ) {
mBuf[ mStrLen + 1 ] = '\0';
return &mBuf[1]; }
else
return "\0";
}
void UtilStr::Append( const char* inCStr ) {
register unsigned long i = 0;
if ( inCStr ) {
while( inCStr[ i ] != '\0' )
i++;
Append( inCStr, i );
}
}
void UtilStr::Append( const unsigned char* inStrPtr ) {
if ( inStrPtr )
Append( (char*) &inStrPtr[1], inStrPtr[0] );
}
void UtilStr::Append( const void* inSrce, long numBytes ) {
unsigned long newLen = numBytes + mStrLen;
char* oldBuf;
if ( numBytes > 0 ) {
if ( newLen >= mBufSize ) {
if ( newLen < 80 )
mBufSize = newLen + 5;
else if ( newLen < 500 )
mBufSize = newLen + 100;
else mBufSize = newLen + 3000;
oldBuf = mBuf;
mBuf = new char[ mBufSize + 2 ]; // One for pascal byte, one for c NUL byte
if ( oldBuf ) {
if ( mStrLen > 0 )
Move( &mBuf[1], &oldBuf[1], mStrLen );
delete oldBuf;
}
}
if ( inSrce && numBytes > 0 )
Move( &mBuf[mStrLen + 1], inSrce, numBytes );
mStrLen = newLen;
}
}
void UtilStr::Append( long inNum ) {
UtilStr temp;
unsigned long i;
if ( inNum < 0 ) {
Append( '-' );
inNum = - inNum;
}
if ( inNum == 0 )
Append( '0' );
while ( inNum > 0 ) {
temp.Append( (char) ('0' + inNum % 10) );
inNum = inNum / 10;
}
for ( i = temp.length(); i > 0; i-- )
Append( temp.getChar( i ) );
}
void UtilStr::Append( const UtilStr* inStr ) {
if ( inStr )
Append( inStr -> getCStr(), inStr -> length() );
}
void UtilStr::Assign( const UtilStr& inStr ) {
if ( this != &inStr ) {
Wipe();
Append( inStr.getCStr(), inStr.length() );
}
}
void UtilStr::Assign( const void* inPtr, long bytes ) {
Wipe();
Append( inPtr, bytes );
}
void UtilStr::Assign( char inChar ) {
Wipe();
Append( &inChar, 1 );
}
void UtilStr::Assign( long inNum ) {
Wipe();
Append( inNum );
}
void UtilStr::Assign( const unsigned char* inStrPtr ) {
Wipe();
Append( inStrPtr );
}
void UtilStr::Assign( const UtilStr* inStr ) {
if ( inStr != this ) {
Wipe();
if ( inStr )
Append( inStr -> getCStr(), inStr -> length() );
}
}
void UtilStr::Assign( CEgIStream& inStream, long numBytes ) {
if ( numBytes > 5000000 ) // *** Safe to say that sizes over this are corrupt?
inStream.throwErr( cCorrupted );
else if ( numBytes > 0 ) {
Dim( numBytes );
if ( length() < numBytes )
numBytes = length();
inStream.GetBlock( getCStr(), numBytes );
}
}
void UtilStr::ReadFrom( CEgIStream* inStream ) {
unsigned long len = inStream -> GetLong(); // Grab the length
Assign( *inStream, len );
}
void UtilStr::WriteTo( CEgOStream* inStream ) const {
inStream -> PutLong( length() );
inStream -> PutBlock( getCStr(), length() );
}
void UtilStr::Prepend( char inChar ) {
Insert( 0, &inChar, 1 );
}
void UtilStr::Prepend( UtilStr& inStr ) {
Insert( 0, inStr.getCStr(), inStr.length() );
}
void UtilStr::Prepend( const char* inStr ) {
long len = 0;
while ( *(char*)(inStr + len) != 0 )
len++;
Insert( 0, inStr, len );
}
void UtilStr::Insert( unsigned long inPos, char inChar, long inNumTimes ) {
unsigned long oldLen = length();
unsigned long numAddable;
if ( inPos > oldLen )
inPos = oldLen;
Insert( inPos, (char*) NULL, inNumTimes );
numAddable = length() - oldLen;
if ( numAddable > 0 && mBuf ) {
while ( inNumTimes > 0 ) {
mBuf[ inPos + inNumTimes ] = inChar;
inNumTimes--;
}
}
}
void UtilStr::Insert( unsigned long inPos, long inNum ) {
UtilStr numStr( inNum );
Insert( inPos, numStr );
}
void UtilStr::Insert( unsigned long inPos, const UtilStr& inStr ) {
Insert( inPos, inStr.getCStr(), inStr.length() );
}
void UtilStr::Insert( unsigned long inPos, const char* inSrce, long inBytes ) {
unsigned long numToMove, len = length();
if ( inPos >= len )
Append( inSrce, inBytes );
else if ( inBytes > 0 ) {
Append( NULL, inBytes );
numToMove = len - inPos;
if ( numToMove > 0 )
Move( &mBuf[ inPos + inBytes + 1 ], &mBuf[ inPos + 1 ], numToMove );
if ( inBytes > 0 && inSrce )
Move( &mBuf[ inPos + 1 ], inSrce, inBytes );
}
}
void UtilStr::Move( void* inDest, const void* inSrce, unsigned long inNumBytes ) {
if ( inNumBytes <= 64 ) {
register unsigned char* dest = (unsigned char*) inDest;
register unsigned char* srce = (unsigned char*) inSrce;
if ( srce > dest )
while ( inNumBytes > 0 ) {
*dest = *srce;
dest++;
srce++;
inNumBytes--;
}
else {
dest += inNumBytes;
srce += inNumBytes;
while ( inNumBytes > 0 ) {
dest--;
srce--;
*dest = *srce;
inNumBytes--;
} } }
else
#ifdef EG_WIN
::MoveMemory( inDest, inSrce, inNumBytes );
#elif EG_MAC
::BlockMove( inSrce, inDest, inNumBytes );
#else
You must have EG_MAC or EG_WIN and EG_WIN32 defined as 1 to compile Common!
#endif
}
void UtilStr::Decapitalize() {
unsigned long i, len = length();
unsigned char c, sp;
for( i = 2; i <= len; i++ ) {
c = getChar( i );
sp = getChar( i-1 );
if ( ( sp >= 'A' && sp <= 'Z' ) || ( sp >= 'a' && sp <= 'z' ) ) {
if ( getChar( i-1 ) == 'I' && c == 'I' ) { } // Prevent III from decapitalizing
else if ( c >= 'A' && c <= 'Z' )
setChar( i, c + 32 );
}
}
}
void UtilStr::Capitalize() {
unsigned long i, len = length();
char c;
for( i = 1; i <= len; i++ ) {
c = getChar( i );
if ( c >= 'a' && c <= 'z' ) {
setChar( i, c - 32 );
}
}
}
void UtilStr::Trunc( unsigned long numToChop, bool fromRight ) {
if ( fromRight )
Remove( length() - numToChop + 1, numToChop );
else
Remove( 1, numToChop );
}
void UtilStr::Remove( unsigned long inPos, unsigned long inNum ) {
unsigned long toMove;
unsigned long len = length();
if ( inPos < 1 )
inPos = 1;
if ( inNum > len - inPos + 1 )
inNum = len - inPos + 1;
if ( inPos <= len && inNum > 0 ) {
mStrLen = len - inNum;
toMove = len - inPos - inNum + 1;
if ( toMove > 0 )
Move( &mBuf[ inPos ], &mBuf[ inPos + inNum ], toMove );
}
}
void UtilStr::Remove( char* inStr, int inLen, bool inCaseSensitive ) {
long pos;
char* s;
if ( inLen < 0 ) {
inLen = 0;
s = inStr;
while ( *s ) {
inLen++;
s++;
}
}
pos = contains( inStr, inLen, 0, inCaseSensitive );
while ( pos > 0 ) {
Remove( pos, inLen );
pos--;
pos = contains( inStr, inLen, pos, inCaseSensitive );
}
}
void UtilStr::Keep( unsigned long inNumToKeep ) {
if ( inNumToKeep < length() )
Trunc( length() - inNumToKeep, true );
}
void UtilStr::PoliteKeep( unsigned long inMaxLen, unsigned long inPos ) {
if ( length() > inMaxLen ) {
Remove( inPos + 1, length() - inMaxLen + 1 );
setChar( inPos, '…' );
}
}
void UtilStr::ZapLeadingSpaces() {
unsigned long i = 1;
unsigned long len = length();
while ( getChar( i ) == ' ' && i <= len )
i++;
if ( i > 1 )
Trunc( i - 1, false );
}
/*
UtilStr UtilStr::MID( unsigned long start, unsigned long inLen ) const {
UtilStr newStr;
unsigned long len = length();
if ( start < 1 )
start = 1;
start--;
if ( inLen > len - start )
inLen = len - start;
if ( start <= len && inLen > 0 )
newStr.Assign( getCStr() + start, inLen );
return newStr;
}
UtilStr UtilStr::RIGHT( unsigned long inLen ) const {
UtilStr newStr;
unsigned long start, len = length();
if ( inLen > len )
inLen = len;
start = len - inLen;
newStr.Assign( getCStr() + start, inLen );
return newStr;
}
*/
long UtilStr::FindNextInstanceOf( long inPos, char c ) const {
long len = length(), i;
if ( inPos < 0 )
inPos = 0;
for ( i = inPos+1; i <= len; i++ ) {
if ( mBuf[ i ] == c )
return i;
}
return 0;
}
long UtilStr::FindPrevInstanceOf( long inPos, char c ) const {
long i;
if ( inPos > length() )
inPos = length();
for ( i = inPos; i > 0; i-- ) {
if ( mBuf[ i ] == c )
return i;
}
return 0;
}
void UtilStr::Replace( char inTarget, char inReplacement ) {
unsigned long i, len = length();
for ( i = 1; i <= len; i++ )
if ( mBuf[ i ] == inTarget )
mBuf[ i ] = inReplacement;
}
void UtilStr::copyTo( unsigned char* pasDestPtr, unsigned char inBytesToCopy ) const {
unsigned long bytes = length() + 1;
if ( bytes > inBytesToCopy )
bytes = inBytesToCopy;
getPasStr(); // refreshes len byte for pas str
if ( bytes > 255 )
bytes = 255;
Move( pasDestPtr, &mBuf[0], bytes );
}
void UtilStr::copyTo( char* inDestPtr, unsigned long inBytesToCopy ) const {
unsigned long bytes = length() + 1;
if ( bytes > inBytesToCopy )
bytes = inBytesToCopy;
getCStr(); // refreshes NUL byte for c strs
Move( inDestPtr, &mBuf[1], bytes );
}
char UtilStr::getChar( unsigned long i ) const {
if ( i <= mStrLen && i > 0 )
return mBuf[ i ];
else
return '\0';
}
void UtilStr::setChar( unsigned long i, char inChar ) {
if ( i <= mStrLen && i > 0 )
mBuf[ i ] = inChar;
}
int UtilStr::StrCmp( const char* s1, const char* s2, long inN, bool inCaseSensitive ) {
char c1, c2;
if ( inN < 0 ) {
inN = 0;
const char* s = (*s1 != 0) ? s1 : s2;
while ( *s ) {
s++;
inN++;
}
}
while ( inN > 0 ) {
inN--;
c1 = *s1;
s1++;
c2 = *s2;
s2++;
if ( ! inCaseSensitive ) {
if ( c1 >= 'a' && c1 <= 'z' )
c1 -= 32;
if ( c2 >= 'a' && c2 <= 'z' )
c2 -= 32;
}
if ( c1 != c2 )
return c1 - c2;
}
return 0;
}
int UtilStr::compareTo( const unsigned char* inPStr, bool inCaseSensitive ) const {
if ( inPStr ) {
if ( length() == inPStr[0] ) {
return StrCmp( getCStr(), (char*) (inPStr + 1), length(), inCaseSensitive );
}
}
return -1;
}
int UtilStr::compareTo( const UtilStr* inStr, bool inCaseSensitive ) const {
if ( inStr )
return StrCmp( inStr -> getCStr(), getCStr(), length() + 1, inCaseSensitive );
else
return -1;
}
int UtilStr::compareTo( const char* inStr, bool inCaseSensitive ) const {
if ( inStr )
return StrCmp( inStr, getCStr(), length() + 1, inCaseSensitive );
else
return -1;
}
long UtilStr::contains( const char* inSrchStr, int inLen, int inStartingPos, bool inCaseSensitive ) const {
char srchChar, srchCharLC, c;
char* endPtr, *curPtr = getCStr();
if ( inLen < 0 ) {
inLen = 0;
while ( *(inSrchStr+inLen) )
inLen++;
}
endPtr = curPtr + length() - inLen;
srchChar = *inSrchStr;
if ( srchChar >= 'a' && srchChar <= 'z' )
srchChar -= 32;
srchCharLC = srchChar + 32;
if ( inStartingPos > 0 )
curPtr += inStartingPos;
while ( curPtr <= endPtr ) {
c = *curPtr;
if ( c == srchChar || c == srchCharLC ) {
if ( StrCmp( curPtr, inSrchStr, inLen, inCaseSensitive ) == 0 )
return curPtr - getCStr() + 1;
}
curPtr++;
}
return 0;
}
/*
bool UtilStr::equalTo( const char* inStr, int inFlags ) const {
bool stillOk = inStr != NULL;
char* thisStr = getCStr();
char c1 = 1, c2 = 2;
bool caseInsensitive = inFlags & cCaseInsensitive != 0;
while ( stillOk && c2 != 0 ) {
c1 = *inStr;
c2 = *thisStr;
if ( caseInsensitive ) {
if ( c1 >= 'a' && c1 <= 'z' )
c1 -= 32;
if ( c2 >= 'a' && c2 <= 'z' )
c2 -= 32;
}
stillOk = c1 == c2;
thisStr += 1;
inStr += 1;
}
if ( ( inFlags & cLefthand ) && c2 == 0 )
stillOk = true;
return stillOk;
}
*/
long UtilStr::GetIntValue( char* inStr, long inLen, long* outPlacePtr ) {
bool seenNum = false;
char c;
long i, ret = 0, place = 1;
for ( i = inLen - 1; i >= 0; i-- ) {
c = inStr[ i ];
if ( c >= '0' && c <= '9' ) {
seenNum = true;
ret += place * ( c - '0' );
place *= 10; }
else if ( seenNum )
i = 0; // Stop loop
}
if ( outPlacePtr )
*outPlacePtr = place;
return ret;
}
double UtilStr::GetFloatVal( char* inStr, long inLen ) {
unsigned long i, decLoc = 0, foundLet = false;
char c;
double n = 0, place = 1.0;
bool isNeg = false;
for ( i = 0; i < inLen; i++ ) {
c = inStr[ i ];
if ( c == '-' && ! foundLet )
isNeg = true;
if ( c >= '0' && c <= '9' ) {
n = 10.0 * n + ( c - '0' );
if ( decLoc )
place *= 10.0;
}
if ( c != ' ' )
foundLet = true;
if ( c == '.' )
decLoc = i+1;
}
if ( isNeg )
n = - n;
return n / place;
}
double UtilStr::GetFloatValue() const {
return GetFloatVal( mBuf + 1, mStrLen );
}
long UtilStr::GetValue( long inMultiplier ) const {
unsigned long i, len = length(), decLoc = 0, foundLet = false;
char c;
long left, right, place;
for ( i = 1; i <= len; i++ ) {
c = mBuf[ i ];
if ( c == '-' && ! foundLet )
inMultiplier *= -1;
if ( c != ' ' )
foundLet = true;
if ( c == '.' )
decLoc = i;
}
if ( ! decLoc )
decLoc = len + 1;
left = GetIntValue( mBuf + 1, decLoc - 1 );
right = GetIntValue( mBuf + decLoc + 1, len - decLoc, &place );
return ( inMultiplier * right + place / 2 ) / place + inMultiplier * left;
}
void UtilStr::SetValue( long inVal, long inDivisor, int inNumDecPlaces ) {
long i, part = inVal % inDivisor;
UtilStr partStr;
for ( i = 0; i < inNumDecPlaces; i++ )
part *= 10;
part /= inDivisor;
i = inVal / inDivisor;
if ( i != 0 || part <= 0 )
Assign( i );
else
Wipe();
if ( part > 0 ) {
Append( '.' );
partStr.Append( part );
for ( i = inNumDecPlaces - partStr.length(); i > 0; i-- )
Append( '0' );
Append( &partStr );
while ( getChar( length() ) == '0' )
Trunc( 1 );
}
}
void UtilStr::AppendAsMeta( const UtilStr* inStr ) {
if ( inStr )
AppendAsMeta( inStr -> getCStr(), inStr -> length() );
}
void UtilStr::AppendAsMeta( const void* inPtr, long inLen ) {
const unsigned char* ptr = (unsigned char*) inPtr;
unsigned char c;
Append( '"' );
if ( ptr ) {
while ( inLen > 0 ) {
c = *ptr;
if ( c == '"' ) // Our flag was detected...
Append( (char) '"' ); // Two flags in a row signal an actual "
if ( c < 32 || c > 127 ) {
Append( (char) '"' );
Append( (long) c );
Append( (char) '"' ); }
else
Append( &c, 1 );
inLen--;
ptr++;
}
}
Append( '"' );
}
void UtilStr::AppendFromMeta( const void* inPtr, long inLen ) {
const unsigned char* ptr = (unsigned char*) inPtr;
unsigned char c;
static UtilStr ascNum;
if ( ptr ) {
if ( *ptr != '"' ) // First char should be a "
return;
inLen--;
ptr++;
while ( inLen > 1 ) { // We stop 1 char early cuz last char should be a "
c = *ptr;
if ( c == '"' ) { // If the flag is detected...
inLen--;
ptr++;
c = *ptr;
if ( inLen > 1 && c != '"' ) { // Ignore double flags (they signify the flag char)
ascNum.Wipe();
while ( c >= '0' && c <= '9' ) {
ascNum.Append( (char) c );
inLen--;
ptr++;
c = *ptr;
}
c = ascNum.GetValue();
}
}
Append( (char) c );
inLen--;
ptr++;
}
}
}
UtilStr UtilStr::operator + ( const UtilStr& inStr ) {
UtilStr newStr( this );
newStr.Append( &inStr );
return newStr;
}
UtilStr UtilStr::operator + ( const char* inCStr ) {
UtilStr newStr( this );
newStr.Append( inCStr );
return newStr;
}
UtilStr UtilStr::operator + ( long inNum ) {
UtilStr newStr( this );
newStr.Append( inNum );
return newStr;
}
UtilStr& UtilStr::operator = ( const UtilStr& inStr ) {
Wipe();
Append( inStr.getCStr() );
return *this;
}
long UtilStr::Hash() const {
long hash = 0;
const char* stop = getCStr();
const char* curPos = stop + mStrLen - 1;
if ( mStrLen < 16 ) {
// Sample all the characters
while ( curPos >= stop ) {
hash = ( hash * 37 ) + *curPos;
curPos--;
} }
else {
// only sample some characters
int skip = mStrLen / 7;
while ( curPos >= stop ) {
hash = ( hash * 39 ) + *curPos;
curPos -= skip;
}
}
return hash;
}
bool UtilStr::Equals( const Hashable* inComp ) const {
return compareTo( (UtilStr*) inComp ) == 0;
}
void UtilStr::AppendHex( char inB1, char inB2 ) {
unsigned char c;
if ( inB1 >= '0' && inB1 <= '9' )
inB1 -= '0';
else
inB1 = 9 + inB1 & 0xF;
c = inB1 << 4;
if ( inB2 >= '0' && inB2 <= '9' )
c += (inB2 - '0');
else
c += 9 + inB2 & 0xF;
Append( (char) c );
}
/*
long UtilStr::Hash( const char* inStr, long inStrLen ) {
long hash = 0;
const char* curPos = inStr + inStrLen - 1;
if ( inStrLen < 0 )
inStrLen = inStr's len
if ( inStrLen < 16 ) {
// Sample all the characters
while ( curPos >= inStr ) {
hash = ( hash * 37 ) + *curPos;
curPos--;
} }
else {
// only sample some characters
int skip = inStrLen / 7;
while ( curPos >= inStr ) {
hash = ( hash * 39 ) + *curPos;
curPos -= skip;
}
}
return hash;
}(*/